use axum::{extract::{Path, Query}, http::HeaderMap, Json};
use com::{ auth::claims::get_id, code, query, sea_orm::{ bus, connect, delete, fun::concat_expr, send_bus_ok, send_paging, send_sql_ok} };
use sea_orm::{ entity::*, query::* };
use model::project::{ ActiveModel, Column, Entity};

pub async fn list(Query(param): Query<JsonValue>) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let selector = Entity::find()
    .select_only()
    .columns([ Column::Id, Column::Title, Column::Folder, Column::FolderFront, Column::Database, Column::Url, Column::Backup, Column::Enabled ])

    .column_as(concat_expr(vec![Column::ApiUrl.into_simple_expr(),"/api/sys/".into()]), "api_url")
    .column_as(concat_expr(vec![ "mysql://root:123456@localhost:3306/".into(), Column::Database.into_simple_expr() ]), "sql_url")
    .column_as(Column::MgUrl.if_null("mongodb://localhost:27017/"), "mg_url")
    .column_as(Column::RedisUrl.if_null("redis://root:123456@localhost"), "redis_url")

    .apply_if(query::str_op(&param,"title")?,  | q, v| q.filter(Column::Title.contains(v)) )
    .order_by_desc(Column::Enabled.eq(1));
    send_paging(selector, param).await
}
pub async fn save( header: HeaderMap, Json(body):Json<JsonValue> ) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let user = get_id(header)?;
    let mut model = ActiveModel{
        title           : Set( query::str(&body, "title")? ),
        folder          : Set( query::str_op(&body, "folder")? ),
        folder_front    : Set( query::str_op(&body, "folder_front")? ),
        backup          : Set( query::str_op(&body, "backup")? ),
        database        : Set( query::str(&body, "database")? ),
        url             : Set( query::str_op(&body, "url")? ),
        api_url         : Set( query::str_op(&body, "api_url")? ),
        sql_url         : Set( query::str_op(&body, "sql_url")? ),
        mg_url          : Set( query::str_op(&body, "mg_url")? ),
        redis_url       : Set( query::str_op(&body, "redis_url")? ),
        create_user     : Set( user.to_owned() ),
        ..Default::default()
    };
    if let Some(f) = query::i32_op(&body, "id")? {
        model.id = Set(f);
        model.update_user = Set( Some(user) );
        model.create_user = NotSet;
    }
    let result = model.save(&conn).await;
    send_sql_ok(&conn, result).await
}
pub async fn find(Path( id ): Path<i32>) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let result = Entity::find_by_id(id)
    .select_only()
    .columns([ 
        Column::Id, Column::Title, Column::Folder, Column::FolderFront, Column::ApiUrl, Column::Database, Column::Url, Column::Backup,
        Column::SqlUrl, Column::MgUrl, Column::RedisUrl
    ])
    .into_model()
    .one(&conn).await;

    code::send_op_obj( result )
}
pub async fn del(Path( id ): Path<String>) -> Result<Json<JsonValue>, Json<JsonValue>>{ delete::del::by_ids(Entity, &id, None).await }
pub async fn enabled( header: HeaderMap,Path( id ): Path<i32>) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = bus::start().await?;
    let user = get_id(header)?;
    let model = ActiveModel{
        id              : Set( id ),
        enabled        : Set( 1.into() ),
        update_user     : Set( Some(user) ),
        ..Default::default()
    };
    let result = model.save(&conn).await;
    let _ = send_bus_ok(&conn, result).await?;
    let result = Entity::update_many().col_expr(Column::Enabled, 0.into() ).filter(Column::Id.ne(id)).exec(&conn).await;
    let _ = send_bus_ok(&conn, result).await?;
    code::send_ok(conn.commit().await)
}
pub async fn info() -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let result = Entity::find()
    .select_only()
    .columns([ Column::Id, Column::Title, Column::Folder, Column::FolderFront, Column::Database, Column::Url, Column::Backup ])
    .column_as(concat_expr(vec![Column::ApiUrl.into_simple_expr(),"/api/sys/".into()]), "api")
    .column_as(concat_expr(vec![ "mysql://root:123456@localhost:3306/".into(), Column::Database.into_simple_expr() ]), "sql")
    .column_as(Column::MgUrl.if_null("mongodb://localhost:27017/"), "mongodb")
    .column_as(Column::RedisUrl.if_null("redis://root:123456@localhost"), "redis")

    .filter(Column::Enabled.eq(1))
    .into_json().one(&conn).await;
    code::send_op_obj(result)
}
pub async fn database() -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let result = Entity::find()
    .select_only()
    .columns([ Column::Id, Column::Database, Column::Backup ])
    .into_json().all(&conn).await;
    code::send_arr(result)
}
pub async fn dict(Query(param): Query<JsonValue>) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let result = Entity::find()
    .select_only()
    .columns([ Column::Id ])
    .column_as(Column::Id,"value")
    .column_as(Column::Title, "label")
    .apply_if(query::str_op(&param,"title")?,  | q, v| q.filter(Column::Title.contains(v)) )
    .order_by_desc(Column::Enabled.eq(1))
    .into_json().all(&conn).await;
    code::send_arr(result)
}